[Amazon Lex] HTML+JavaScriptで作成したLexクライアントでカード情報の表示に対応してみました。
1 はじめに
こんにちは、Alソリューション部の平内(SIN)です。
Amazon Lex(以下、Lex)のAPIであるPostText()のレスポンスには、カード情報を追加することが出来ます。
今回は、前回作成したLexクライアントで、このカード情報を表示できるようにして見ました。
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました)
最初に、動作しているようすです。花の種類を聞き取る段階で、送られてきたカードを表示しています。選択は、ボタンで行うことも出来ます。
2 Prompt response cards
カードの情報は、コンソールでもLambdaからでも設定可能です、今回は、コンソールで以下のように設定しました。
3 ResponseCardオブジェクト
ResponseCardにセットされるオブジェクトの内容は以下のとおりです。
(1) ResponseCard
ResponseCardの各アイテムは、以下のとおりです。
Name | Type | Required | Detail |
---|---|---|---|
contentType | String | No | application/vnd.amazonaws.card.generic |
genericAttachments | Array of GenericAttachment | No | 0〜10個のアイテム |
version | String | No | ResponseCardのフォーマットのバージョン |
(2) GenericAttachment
ResponseCardのgenericAttachments配列に設定されるオブジェクトで、表示されるオプションを表します。 画像、ボタン、リンク、又はテキストです。
Name | Type | Required | Detail |
---|---|---|---|
attachmentLinkUrl | String | No | 1〜2048文字 |
buttons | Array of Button | No | 0〜5個のアイテム |
imageUrl | String | No | 1〜2048文字 |
subTitle | String | No | 1〜80文字 |
title | String | No | 1〜80文字 |
(3) Button
GenericAttachmentのbuttons配列に設定されるオブジェクトで、表示されるテキスト及び、それを押されたときに返す値です。
Name | Type | Required | Detail |
---|---|---|---|
text | String | Yes | 1〜15文字 |
value | String | Yes | 1〜1000文字 |
4 クライントの実装
実装したコードは、以下のとおりです。 Lexからの戻り値にresponseCardがあった時に、それを表示しています。
<br /> <center>Order Flowers</center><script src="https://sdk.amazonaws.com/js/aws-sdk-2.283.1.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <style language="text/css"> <p> div#logView {<br /> background-color:darkturquoise;<br /> border: 1px solid #ccc;<br /> padding: 4px;<br /> width: 400px;<br /> height: 500px;<br /> overflow: scroll;<br /> }</p> <p> div#logView2 {<br /> background-color:darkturquoise;<br /> border: 1px solid #ccc;<br /> padding: 4px;<br /> width: 400px;<br /> height: 500px;<br /> overflow: scroll;<br /> }</p> <p> .card {<br /> float: left;<br /> padding: 4px;<br /> background-color:white;<br /> text-align:center;<br /> }<br /> .card img {<br /> width: 100%;<br /> }<br /> .card button {<br /> margin: 2px;<br /> width: 60%;<br /> height:30px;<br /> border-radius:10px;<br /> background-color:royalblue;<br /> color:white;<br /> font-weight:bolder;<br /> }<br /> .card .title {<br /> font-weight:bolder;<br /> }</p> <p> input#message {<br /> padding: 4px;<br /> font-size: 1em;<br /> width: 400px<br /> }</p> <p> log {<br /> margin: 4px;<br /> padding: 4px;<br /> border-radius: 4px;<br /> min-width: 50%;<br /> max-width: 85%;<br /> }</p> <p> log.req {<br /> float: left;<br /> background-color:white;<br /> }</p> <p> log.res {<br /> text-align: right;<br /> float: right;<br /> background-color:beige;<br /> }<br /> log.err {<br /> text-align: right;<br /> float: right;<br /> color: #f77;<br /> }<br /> </style> <script> $('#message').focus(); AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx', }); const lexruntime = new AWS.LexRuntime(); let sessionAttributes = {}; const botAlias = '$LATEST'; const botName = 'OrderFlowers'; const userId = 'id-' + Date.now(); function pushChat() { const message = $('#message').val().trim(); if(message.length > 0) { $('#message').val(''); const params = { botAlias: botAlias, botName: botName, inputText: message, userId: userId, sessionAttributes: sessionAttributes }; appendLog(message, 'req'); lexruntime.postText(params, function(err, data) { if (err) { console.log(err, err.stack); appendLog(err.message, 'err'); } if (data) { console.log(JSON.stringify(data)); sessionAttributes = data.sessionAttributes; appendLog(data.message, 'res'); if(data.responseCard) { appendCard(data.responseCard); } } }); } return false; } function appendLog(message, className) { $('<log>', { class:className, text:message }).appendTo('#logView'); $('#logView').scrollTop(self.innerHeight); } function appendCard(responseCard) { const genericAttachments = responseCard.genericAttachments; genericAttachments.forEach(genericAttachment => { const card = $('</p> <div class="card"></div> <p>'); const imageUrl = genericAttachment.imageUrl; const title = genericAttachment.title; const subTitle = genericAttachment.subTitle; $('<img src=' + imageUrl + '>').appendTo(card); $('</p> <div class="title">' + title + '</div> <p>').appendTo(card); $('</p> <div>' + subTitle + '</div> <p>').appendTo(card); const buttons = genericAttachment.buttons; buttons.forEach(button => { const b = $('<button>' + button.text + '</button>'); b.click(function(){ $('#message').val(button.value); pushChat(); }); b.appendTo(card); }) card.appendTo('#logView'); }); $('#logView').scrollTop(self.innerHeight); } </script> <div id="logView"></div> <form><input id="message" size="80" type="text" value="" /></form>
5 最後に
今回は、HTML+JavaScriptのLexクライアントでカード情報に対応してみました。
何故(当然)か、オーディオ対応のPostContent()では、ResponseCardを返すことが出来ません。
ってことは、音声対応のLexクライアントでは、音声でもボタンでも応答可能なリッチなクライアントは、ResponseCardでは、対応できないことになります。
Lambda側の実装で、SessionAttributesに、ResponseCardと同じ内容を返すなどの工夫が必要のようです。次回は、この辺の仕様を検討して、音声対応のLexクライアントでもカード表示に対応させて見たいと思います。
6 参考リンク
Amazon Lex Runtime Service » PostText
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました)
[Amazon Lex] HTML+JavaScriptでLexクライアントを作ってみました(音声対応)
弊社ではAmazon Connectのキャンペーンを行なっております。
3月に引き続き、4月も「無料Amazon Connectハンズオンセミナー」を開催致します。導入を検討されておられる方は、是非、お申し込み下さい。
また音声を中心とした各種ソリューションの開発支援も行なっております。